package com.liuzy.ioc;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * Bean工厂
 * 
 * @author liuzy
 * @version 2015年5月13日
 */
public final class BeanFactory {

	/** Bean仓库-名称 */
	private static Map<String, Object> beanMap = new HashMap<String, Object>();
	
    /** Bean仓库2-类型 */
    private static final Map<Class<?>, Object> beanMap2 = new HashMap<Class<?>, Object>();
	
	private BeanFactory() {
		
	}

	/**
	 * 根据XML配置文件,初始化Bean实例
	 * @param xml
	 */
	public static void init(String xml) {
		try {
			// 读取指定的配置文件
			SAXReader reader = new SAXReader();
			ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
			// 从class目录下获取指定的xml文件
			InputStream ins = classLoader.getResourceAsStream(xml);
			Document doc = reader.read(ins);
			Element _beans = doc.getRootElement();
			Element _bean;
			// 遍历bean
			for (Iterator<?> _beans_i = _beans.elementIterator("bean"); _beans_i.hasNext();) {
				_bean = (Element) _beans_i.next();
				// 获取bean的属性id和class
				String id = _bean.attribute("id").getText();
				String clazz = _bean.attribute("class").getText();
				Class<?> beanClass = Class.forName(clazz);
				Field[] beanFields = beanClass.getDeclaredFields();
				Object obj = beanClass.newInstance();
				// 遍历该bean的property属性
				for (Iterator<?> _bean_i = _bean.elementIterator("property"); _bean_i.hasNext();) {
					Element _property = (Element) _bean_i.next();
					// 获取该property的name和value
					String name = _property.attribute("name").getText();
					String value = ((Element) _property.elementIterator("value").next()).getText();
					// 把属性值set到对象
					for (Field field : beanFields) {
						if (name.equals(field.getName())) {
							field.setAccessible(true);// 必须使该字段可访问
							field.set(obj, value);
							break;
						}
					}
				}
				beanMap.put(id, obj);
				beanMap2.put(beanClass, obj);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static Object getBean(String beanName) {
		return beanMap.get(beanName);
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T getBean(Class<T> clazz) {
        return (T) beanMap2.get(clazz);
    }
}